﻿using System;
using EnvDTE80;
using System.Windows.Forms;
using LazyPlugins.AttachManager;
using LazyPlugins.AutoAttacher.Properties;
using LazyPlugins.AutoAttacher.UI;

namespace LazyPlugins.AutoAttacher.CustomActions
{
    public class ActionsHelper
    {
        private bool isWaiting;

        #region Properties

        public string ProcessName
        {
            get
            {
                return Settings.Default.ProcessName;
            }
            set
            {
                Settings.Default.ProcessName = value;
                Settings.Default.Save();
            }
        }

        public int WaitTimeout
        {
            get
            {
                return Settings.Default.WaitTimeout;
            }
            set
            {
                Settings.Default.WaitTimeout = value;
                Settings.Default.Save();
            }
        }


        #endregion

        #region private
        private static ActionsHelper instance;
        private static readonly object padlock = new object();
        private readonly ProcessAttacher processAttacher;
        #endregion

        #region private methods

        private void AttachWithWaitingForm(Action<string,int> attach)
        {
            lock (this)
            {
                if (!isWaiting)
                {
                    isWaiting = true;
                    var waitForm = new WaitToAttach(WaitTimeout);
                    waitForm.Show();
                    attach.BeginInvoke(ProcessName, WaitTimeout, result =>
                    {
                        try
                        {
                            attach.EndInvoke(result);
                            waitForm.SafeClose();

                        }
                        finally
                        {
                            isWaiting = false;
                        }
                    }, null);
                }
            }
        }

        #endregion
        
        #region ctor
		
        private ActionsHelper(DTE2 applicationObject)
        {
            processAttacher = new ProcessAttacher(new DebuggerInfo(applicationObject));
        }

    	#endregion        

        #region singleton 

        public static ActionsHelper GetInstance(DTE2 applicationObject)
        {
            lock(padlock)
            {
                if(instance == null)
                {
                    instance = new ActionsHelper(applicationObject);
                }
                return instance;
            }
        }

        #endregion

        #region public

        public void OptimisticManaged()
        {
            processAttacher.OptimisticAttachManaged(ProcessName);
        }
        public void PessimisticManaged()
        {
            AttachWithWaitingForm(processAttacher.PessimisticAttachManaged);
        }
        public void OptimisticNative()
        {
            processAttacher.OptimisticAttachNative(ProcessName);
        }
        public void PessimisticNative()
        {
            AttachWithWaitingForm(processAttacher.PessimisticAttachNative);
        }
        public void OptimisticNativeAndManaged()
        {
            processAttacher.OptimisticAttachManagedAndNative(ProcessName);
        }
        public void PessimisticNativeAndManaged()
        {
            AttachWithWaitingForm(processAttacher.PessimisticAttachManagedAndNative);
        }

        public void Options()
        {
            var options = new Options(ProcessName, WaitTimeout);
            if(options.ShowDialog() == DialogResult.OK)
            {
                ProcessName = options.ProcessName;
                WaitTimeout = options.WaitTimeout;
            }
        }


        #endregion
    }
}
